package com.quantgroup.data.util;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.file.FileReader;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpUtil;
import org.apache.tools.tar.TarEntry;
import org.apache.tools.tar.TarInputStream;

import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.text.MessageFormat;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.HashMap;
import java.util.Map;
import java.util.zip.GZIPInputStream;

/**
 * 非实时数据获取类
 * @author osmondy
 * @create 2021/9/16 21:15
 */
public class NonRealTimeDataAcquisition {

    /**
     * 源文件目录：           /mnt/ods_inc/src_data/yyyy-mm-dd/s00/s00_android_install
     * 目标文件目录（不要表头）：/mnt/ods_inc/data/yyyy-mm-dd/s00/s00_android_install
     */
    private static String OUTPUT_DIR = "/mnt/ods_inc/src_data/{0}/s00/s00_{1}_{2}";
//    private static String OUTPUT_DIR = "D:/mnt/ods_inc/src_data/{0}/s00/s00_{1}_{2}";

    public static void pullData(String[] args) throws Exception {
//        log.error("开始时间：" + LocalDateTime.now());

        Map<String, String> iosUrlMap = new HashMap<String, String>(16) {{
            put("asaconversion", "http://new.trackingio.com/api/external/download/asaconversion?token=940F1A7D504D7DA9E8AA803A8FB15D2E");
            put("asareg", "http://new.trackingio.com/api/external/download/asareg?token=940F1A7D504D7DA9E8AA803A8FB15D2E");
            put("asalogin", "http://new.trackingio.com/api/external/download/asaloggedin?token=940F1A7D504D7DA9E8AA803A8FB15D2E");
            put("asapay", "http://new.trackingio.com/api/external/download/asapay?token=940F1A7D504D7DA9E8AA803A8FB15D2E");
            put("install", "http://www.trackingio.com/api/external/download/inst?token=940F1A7D504D7DA9E8AA803A8FB15D2E");
            put("reged", "http://www.trackingio.com/api/external/download/reg?token=940F1A7D504D7DA9E8AA803A8FB15D2E");
            put("loggedin", "http://www.trackingio.com/api/external/download/loggedin?token=940F1A7D504D7DA9E8AA803A8FB15D2E");
            put("pay", "http://www.trackingio.com/api/external/download/pay?token=940F1A7D504D7DA9E8AA803A8FB15D2E");
            put("order", "http://www.trackingio.com/api/external/download/order?token=940F1A7D504D7DA9E8AA803A8FB15D2E");
        }};

        Map<String, String> androidUrlMap = new HashMap<String, String>(8) {{
            put("install", "http://www.trackingio.com/api/external/download/inst?token=1BC8D100AAE847AF964E44FD0DD1F9EF");
            put("reged", "http://www.trackingio.com/api/external/download/reg?token=1BC8D100AAE847AF964E44FD0DD1F9EF");
            put("loggedin", "http://www.trackingio.com/api/external/download/loggedin?token=1BC8D100AAE847AF964E44FD0DD1F9EF");
            put("pay", "http://www.trackingio.com/api/external/download/pay?token=1BC8D100AAE847AF964E44FD0DD1F9EF");
            put("order", "http://www.trackingio.com/api/external/download/order?token=1BC8D100AAE847AF964E44FD0DD1F9EF");
        }};

        Map<String, String> wxUrlMap = new HashMap<String, String>(8) {{
            put("install", "http://www.trackingio.com/api/external/download/inst?token=4463B801EDEACCB9DC4D18CFFEDC0910");
            put("reged", "http://www.trackingio.com/api/external/download/reg?token=4463B801EDEACCB9DC4D18CFFEDC0910");
            put("loggedin", "http://www.trackingio.com/api/external/download/loggedin?token=4463B801EDEACCB9DC4D18CFFEDC0910");
            put("pay", "http://www.trackingio.com/api/external/download/pay?token=4463B801EDEACCB9DC4D18CFFEDC0910");
            put("order", "http://www.trackingio.com/api/external/download/order?token=4463B801EDEACCB9DC4D18CFFEDC0910");
        }};

        //客户端
        Map<String, Map<String, String>> clientMap = new HashMap<>(4);
        clientMap.put("ios", iosUrlMap);
        clientMap.put("android", androidUrlMap);
        clientMap.put("wx", wxUrlMap);
        // 参数: 日期+客户端+任务类型
        // 获取参数1日期:格式化日期
        LocalDate yesterday = LocalDate.now().minusDays(1);
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd");
        String formatYesterday = yesterday.format(formatter);

        singleExec(args, clientMap, formatYesterday);
//        batchExec(clientMap, formatYesterday);

//        log.error("结束时间：" + LocalDateTime.now());
    }

    /**
     * 单个任务执行
     * @param args
     * @param clientMap
     * @param formatYesterday
     * @throws Exception
     */
    private static void singleExec(String[] args, Map<String, Map<String, String>> clientMap, String formatYesterday) throws Exception {
        // 校验第二个传参
        if (!args[1].contains("_")) {
            throw new Exception("请输入正确的传参！");
        }
        // 解析传参
        String[] param = args[1].split("_");
        // 获取参数2客户端
        String client = param[1];
        // 获取参数3任务类型
        String type = param[2];
        Map<String, String> clientTaskUrlMap = clientMap.get(client);
        String downloadPath = clientTaskUrlMap.get(type);
        if (StrUtil.isBlank(downloadPath)) {
//                log.error("无法找到下载数据的具体地址");
            throw new Exception("无法找到下载数据的具体地址！");
        }
        //下载文件
        String formatUrl = MessageFormat.format(OUTPUT_DIR, formatYesterday, client, type);
        buildData(downloadPath, formatUrl);
    }

    /**
     * 批量任务执行
     * @param clientMap
     * @param formatYesterday
     * @throws Exception
     */
    private static void batchExec(Map<String, Map<String, String>> clientMap, String formatYesterday) throws Exception {
        //遍历客户端Map
        for (Map.Entry<String, Map<String, String>> clientMapEntry : clientMap.entrySet()) {
            String client = clientMapEntry.getKey();
            Map<String, String> downloadPathMap = clientMapEntry.getValue();
            //遍历具体下载路径Map
            for (Map.Entry<String, String> entry : downloadPathMap.entrySet()) {
                String type = entry.getKey();
                String downloadPath = entry.getValue();
                //下载文件
                String formatUrl = MessageFormat.format(OUTPUT_DIR, formatYesterday, client, type);
                buildData(downloadPath, formatUrl);
            }
        }
    }


    private static void buildData(String value, String formatUrl) throws Exception {
        String destFileUrl = formatUrl + ".tar.gz";
        downloadFile(value, destFileUrl);
        //解压
        File file = new File(destFileUrl);
        String unTarGzUrl = unTarGz(file, formatUrl);
        if (StrUtil.isBlank(unTarGzUrl)) {
            throw new Exception("解压的地址存在问题");
        }
        //处理数据
        handleData(unTarGzUrl);
    }

    /**
     * 下载文件
     *
     * @param downloadPath 下载链接地址
     * @param destPath     目标地址
     * @throws Exception
     */
    public static void downloadFile(String downloadPath, String destPath) throws Exception {
        HttpURLConnection conn = (HttpURLConnection) new URL(downloadPath).openConnection();
        //获取到重定向的字段
        String url = conn.getHeaderField("Location");
        //下载文件
        HttpUtil.downloadFile(url, FileUtil.file(destPath));
    }

    //-----------------------------------------解压-------------------------------------------------------------

    /**
     * 解压tar.gz 文件
     *
     * @param file      要解压的tar.gz文件对象
     * @param outputDir 要解压到某个指定的目录下
     * @throws IOException
     */
    public static String unTarGz(File file, String outputDir) throws IOException {
        String unTarGzUrl = null;
        TarInputStream tarIn = null;
        try {
            tarIn = new TarInputStream(new GZIPInputStream(new BufferedInputStream(new FileInputStream(file))), 1024 * 2);

            //创建输出目录
            createDirectory(outputDir, null);

            TarEntry entry = null;
            while ((entry = tarIn.getNextEntry()) != null) {
                //是目录
                if (entry.isDirectory()) {
                    entry.getName();
                    //创建空目录
                    createDirectory(outputDir, entry.getName());
                } else {//是文件
                    File tmpFile = new File(outputDir + "/" + entry.getName());
                    unTarGzUrl = tmpFile.getAbsolutePath();
                    //创建输出目录
                    createDirectory(tmpFile.getParent() + "/", null);
                    OutputStream out = null;
                    try {
                        out = new FileOutputStream(tmpFile);
                        int length = 0;
                        byte[] b = new byte[2048];
                        while ((length = tarIn.read(b)) != -1) {
                            out.write(b, 0, length);
                        }
                    } catch (IOException ex) {
                        throw ex;
                    } finally {
                        if (out != null) {
                            out.close();
                        }
                    }
                }
            }
        } catch (IOException ex) {
            throw new IOException("解压归档文件出现异常", ex);
        } finally {
            try {
                if (tarIn != null) {
                    tarIn.close();
                }
            } catch (IOException ex) {
                throw new IOException("关闭tarFile出现异常", ex);
            }
        }
        return unTarGzUrl;
    }

    /**
     * 构建目录
     *
     * @param outputDir
     * @param subDir
     */
    public static void createDirectory(String outputDir, String subDir) {
        File file = new File(outputDir);
        //子目录不为空
        if (!(subDir == null || "".equals(subDir.trim()))) {
            file = new File(outputDir + "/" + subDir);
        }
        if (!file.exists()) {
            if (!file.getParentFile().exists()) {
                file.getParentFile().mkdirs();
            }
            file.mkdirs();
        }
    }

    //-----------------------------------------读取处理数据-------------------------------------------------------------

    /**
     * 处理数据
     *
     * @param unTarGzUrl 解压后的文件地址
     * @throws Exception
     */
    public static void handleData(String unTarGzUrl) throws Exception {

        FileReader fileReader = new FileReader(unTarGzUrl);
        String result = fileReader.readString();
        String[] split = result.split("\n");

        StringBuffer buffer = new StringBuffer();
        if (split.length > 0) {
            for (int i = 1; i < split.length; i++) {
                String s = split[i];
                s = s.replaceAll("\t", "\001");
                buffer.append(s);
            }

            //导出处理后的文件
            String destUrl = unTarGzUrl.replace("src_", "");
            FileUtil.writeUtf8String(buffer.toString(), destUrl);
        }
    }


    //-----------------------------------------读取处理数据-------------------------------------------------------------
    /**
     * 处理解压数据
     * @param args
     */
    public static void main(String[] args) throws Exception {
        String url = "D:\\mnt\\ods_inc\\src_data\\20210925\\s00\\s00_android_loggedin\\loggedin_3681b6a12a35fe301bd6b0b8cf4a94fe_2021-09-25.txt";
        specialHandle(url);
//        handleData(url);

    }

    /**
     * 特殊处理
     * @param url
     */
    public static void specialHandle(String url) {
        FileReader fileReader = new FileReader(url);
        String result = fileReader.readString();
        String[] split = result.split("\n");

        StringBuffer buffer = new StringBuffer();
        if (split.length > 0) {
            for (int i = 1; i < split.length; i++) {
                //每一行数据
                String s = split[i];
                String[] row = s.split("\t");
                for (int j = 0; j < row.length; j++) {
                    if (j != 3 && j != 4 && j != 11 && j != 12 && j != 13 && j != 14) {
                        if (j == row.length - 1) {
                            buffer.append(row[j]);
                        } else {
                            buffer.append(row[j]).append("\001");
                        }
                    }
                }
            }

            //导出处理后的文件
            String destUrl = url.replace("src_", "");
            FileUtil.writeUtf8String(buffer.toString(), destUrl);
        }
    }


}
